package engine.asset
{
	import engine.core.*;
	import engine.graphics.resources.*;
	import engine.loaders.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.system.*;
	import flash.utils.*;
	
	public class RxAssetImage extends RxAsset
	{
		private var m_compressedByteArray:ByteArray;
		private var m_decompressedBitmapData:BitmapData;
		private var m_gpuTexture:RxGPUTexture2D;
		private var m_gpuUploadCallback:RxCallback;
		private var m_imageForms:uint;
		private var m_decoder:Loader;
		private var m_decoderContext:LoaderContext;
		private static var s_type:int;
		public static const IMAGE_FORM_COMPRESSED_BYTEARRAY:uint = 1;
		public static const IMAGE_FORM_DECOMPRESSED_BITMAPDATA:uint = 2;
		public static const IMAGE_FORM_GPU_TEXTURE:uint = 4;
		
		public function RxAssetImage()
		{
			super(s_type);
			this.m_compressedByteArray = null;
			this.m_decompressedBitmapData = null;
			this.m_gpuTexture = null;
			this.m_gpuUploadCallback = null;
			this.m_decoder = null;
			this.m_decoderContext = null;
			this.m_imageForms = IMAGE_FORM_DECOMPRESSED_BITMAPDATA;
		}
		
		public static function Initialize() : void
		{
			s_type = RxAsset.RegisterType("image", CreateFromXML);
		}
		
		public static function CreateFromXML(xml:XML, param2:String) : RxAssetImage
		{
			var name:* = xml.@name;
			var url:* = xml.@url;
			url = RxUtilities.MergePath(param2, url);
			return Create(url, name);
		}
		
		public static function Create(param1:String, param2:String) : RxAssetImage
		{
			var _loc_3:* = GetByURL(param1);
			if (_loc_3 != null)
			{
				var _loc_4:* = _loc_3;
				var _loc_5:* = _loc_3.m_references + 1;
				_loc_4.m_references = _loc_5;
				return _loc_3;
			}
			_loc_3 = new RxAssetImage;
			_loc_3.SetURL(param1);
			_loc_3.SetName(param2);
			return _loc_3;
		}
		
		public static function GetByURL(param1:String) : RxAssetImage
		{
			return RxAssetImage(_getByURL(param1, s_type));
		}
		
		override public function Load() : void
		{
			var _loc_1:int = 0;
			super.Load();
			if (m_usedByGPU)
			{
				this.m_imageForms = this.m_imageForms | IMAGE_FORM_GPU_TEXTURE;
			}
			switch(m_state)
			{
				case STATE_EMPTY:
				{
					if (this.m_imageForms & IMAGE_FORM_COMPRESSED_BYTEARRAY)
					{
						_loc_1 = RxLoader.TYPE_DATA;
					}
					else
					{
						_loc_1 = RxLoader.TYPE_IMAGE;
					}
					m_loader = StartLoad(m_url, _loc_1, this.OnLoadComplete);
					m_state = STATE_LOADING;
					break;
				}
				case STATE_LOADING:
				{
					break;
				}
				case STATE_ERROR:
				{
					ExecuteCallbacks(false);
					break;
				}
				case STATE_READY:
				{
					ExecuteCallbacks(true);
					break;
				}
				default:
				{
					break;
				}
			}
		}
		
		private function OnLoadComplete(param1:RxLoaderCallback) : void
		{
			var _loc_2:Bitmap = null;
			if (!param1.m_result)
			{
				m_state = STATE_ERROR;
				ExecuteCallbacks(false);
				return;
			}
			m_size = param1.m_loader.GetSizeInBytes();
			if (this.m_imageForms & IMAGE_FORM_COMPRESSED_BYTEARRAY)
			{
				this.m_compressedByteArray = param1.m_loader.GetData();
				if (this.m_compressedByteArray == null)
				{
					m_state = STATE_ERROR;
					ExecuteCallbacks(false);
					return;
				}
				if (this.m_imageForms & (IMAGE_FORM_DECOMPRESSED_BITMAPDATA | IMAGE_FORM_GPU_TEXTURE))
				{
					this.Decompress();
					return;
				}
			}
			else if (this.m_imageForms & (IMAGE_FORM_DECOMPRESSED_BITMAPDATA | IMAGE_FORM_GPU_TEXTURE))
			{
				_loc_2 = param1.m_loader.GetBitmap();
				this.m_decompressedBitmapData = _loc_2 != null ? (_loc_2.bitmapData) : (null);
				if (this.m_decompressedBitmapData == null)
				{
					m_state = STATE_ERROR;
					ExecuteCallbacks(false);
					return;
				}
				if (this.m_imageForms & IMAGE_FORM_GPU_TEXTURE)
				{
					if (s_loadRequestsImmediate)
					{
						this.UploadToGPU(null);
					}
					else
					{
						this.m_gpuUploadCallback = new RxCallback(this.UploadToGPU);
						s_worker.AddTask(RxTimerWorker.PRIORITY_NORMAL, this.m_gpuUploadCallback);
					}
					return;
				}
			}
			m_state = STATE_READY;
			ExecuteCallbacks(true);
		}
		
		public function GetBitmapData() : BitmapData
		{
			return this.m_decompressedBitmapData;
		}
		
		public function GetCompressedByteArray() : ByteArray
		{
			return this.m_compressedByteArray;
		}
		
		public function SetImageForms(param1:uint) : void
		{
			this.m_imageForms = param1;
		}
		
		public function UnloadDecompressedBitmapData() : void
		{
			if (this.m_decompressedBitmapData != null)
			{
				this.m_decompressedBitmapData.dispose();
				this.m_decompressedBitmapData = null;
				this.CancelUploadToGPU();
			}
			this.UnloadDecoder();
		}
		
		private function CancelUploadToGPU() : void
		{
			if (this.m_gpuUploadCallback != null)
			{
				s_worker.RemoveTask(this.m_gpuUploadCallback, false);
				this.m_gpuUploadCallback = null;
			}
		}
		
		private function UnloadDecoder() : void
		{
			if (this.m_decoder != null)
			{
				if (this.m_decoder.contentLoaderInfo != null)
				{
					if (this.m_decoder.contentLoaderInfo.hasEventListener(Event.COMPLETE))
					{
						this.m_decoder.contentLoaderInfo.removeEventListener(Event.COMPLETE, this.OnDecodeComplete);
					}
					if (this.m_decoder.contentLoaderInfo.hasEventListener(IOErrorEvent.IO_ERROR))
					{
						this.m_decoder.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, this.OnDecodeError);
					}
				}
				this.m_decoder.unload();
				this.m_decoder = null;
			}
			this.m_decoderContext = null;
		}
		
		private function OnDecodeComplete(event:Event) : void
		{
			if (this.m_decoder == null)
			{
				m_state = STATE_ERROR;
				ExecuteCallbacks(false);
				return;
			}
			this.m_decoder.contentLoaderInfo.removeEventListener(Event.COMPLETE, this.OnDecodeComplete);
			this.m_decoder.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, this.OnDecodeError);
			this.m_decompressedBitmapData = Bitmap(this.m_decoder.contentLoaderInfo.content).bitmapData;
			this.UnloadDecoder();
			if (this.m_decompressedBitmapData == null)
			{
				m_state = STATE_ERROR;
				ExecuteCallbacks(false);
				return;
			}
			if (this.m_imageForms & IMAGE_FORM_GPU_TEXTURE)
			{
				if (s_loadRequestsImmediate)
				{
					this.UploadToGPU(null);
					return;
				}
				this.m_gpuUploadCallback = new RxCallback(this.UploadToGPU);
				s_worker.AddTask(RxTimerWorker.PRIORITY_NORMAL, this.m_gpuUploadCallback);
				return;
			}
			m_state = STATE_READY;
			ExecuteCallbacks(true);
			return;
		}
		
		private function OnDecodeError(event:IOErrorEvent) : void
		{
			m_state = STATE_ERROR;
			ExecuteCallbacks(false);
		}
		
		private function UploadToGPU(param1:RxCallback) : Boolean
		{
			if (s_context == null || this.m_decompressedBitmapData == null)
			{
				m_state = STATE_ERROR;
				ExecuteCallbacks(false);
				return true;
			}
			this.m_gpuTexture = new RxGPUTexture2D();
			this.m_gpuTexture.CreateFromBitmapData(s_context, this.m_decompressedBitmapData);
			if (this.m_gpuTexture == null)
			{
				m_state = STATE_ERROR;
				ExecuteCallbacks(false);
				return true;
			}
			if ((this.m_imageForms & IMAGE_FORM_DECOMPRESSED_BITMAPDATA) == 0)
			{
				this.UnloadDecompressedBitmapData();
			}
			m_state = STATE_READY;
			ExecuteCallbacks(true);
			return true;
		}
		
		public function Decompress() : Boolean
		{
			if (this.m_compressedByteArray == null)
			{
				return false;
			}
			if (this.m_decompressedBitmapData != null)
			{
				ExecuteCallbacks(true);
				return true;
			}
			if (this.m_decoder == null)
			{
				this.m_decoder = new Loader();
				this.m_decoderContext = new LoaderContext();
				this.m_decoderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
			}
			this.m_decoder.contentLoaderInfo.addEventListener(Event.COMPLETE, this.OnDecodeComplete);
			this.m_decoder.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, this.OnDecodeError);
			this.m_decoder.loadBytes(this.m_compressedByteArray, this.m_decoderContext);
			return true;
		}
	}
}